﻿using ONCFInstall;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.IO;

namespace ONCFInstall.Test
{
  [TestClass()]
  public class ProgramTest
  {
    public TestContext TestContext { get; set; }

    [TestMethod()]
    [DeploymentItem("ONCFInstall.exe")]
    [DeploymentItem("SampleCAB.CAB")]
    public void SkipOSVersionTest()
    {
      string[] args = new string[] { Path.Combine(TestContext.TestDeploymentDir, "samplecab.cab"), "/sv" };

      CommandLineArgs result = Program_Accessor.ParseArgs(args);
      Assert.IsTrue(result.SkipOSVersionCheck);

      args = new string[] { Path.Combine(TestContext.TestDeploymentDir, "samplecab.cab") };

      result = Program_Accessor.ParseArgs(args);
      Assert.IsFalse(result.SkipOSVersionCheck);
    }

    // a small sampling of valid inputs
    string[][] m_validArgs = new string[][]
      {
        new string[] { "samplecab.cab" },
        new string[] { "samplecab.cab", "/skip:test1.txt" },
        new string[] { "samplecab.cab", "/skip:test1.txt,test2.txt" },
        new string[] { "samplecab.cab", "/replace:path1|path2" },
        new string[] { "samplecab.cab", "/replace:A|B,C|D" },
        new string[] { "samplecab.cab", "/replace:path1|path2", "/skip:test1.txt,test2.txt" },
        new string[] { "samplecab.cab", "/skip:test1.txt,test2.txt", "/replace:path1|path2" },
        new string[] { "samplecab.cab", "/sv" },
        new string[] { "samplecab.cab", "/sv", "/skip:test1.txt" },
        new string[] { "samplecab.cab", "/skip:test1.txt,test2.txt", "/sv" },
        new string[] { "samplecab.cab", "/replace:path1|path2", "/sv" },
        new string[] { "samplecab.cab", "/sv", "/replace:A|B,C|D" },
        new string[] { "samplecab.cab", "/replace:path1|path2", "/sv", "/skip:test1.txt,test2.txt" },
        new string[] { "samplecab.cab", "/sv", "/skip:test1.txt,test2.txt", "/replace:path1|path2" },
      };

    [TestMethod()]
    [DeploymentItem("ONCFInstall.exe")]
    [DeploymentItem("SampleCAB.CAB")]
    public void ParseArgsValidTest()
    {
      for(int i = 0 ; i < m_validArgs.GetLength(0) ; i++)
      {
        try
        {
          m_validArgs[i][0] = Path.Combine(TestContext.TestDeploymentDir, m_validArgs[i][0]);
          CommandLineArgs result = Program_Accessor.ParseArgs(m_validArgs[i]);
          Assert.IsNotNull(result, string.Format("ParseArgs failed on args[{0}]", i));
        }
        catch
        {
          Assert.Fail(string.Format("ParseArgs failed on args[{0}]", i));
        }
      }
    }

    // a small sampling of invalid inputs
    string[][] m_invalidArgs = new string[][]
      {
        new string[] { "hello world" },
        new string[] { "samplecab.cab", "/skip:test",  "/foo" },
        new string[] { "missing.cab", "/skip:test",},
        new string[] { "samplecab.cab blah"},
        new string[] { "samplecab.cab", "/skip:file.txt", "/replace" },
        new string[] { "samplecab.cab", "/skip", "/replace:A|B" },
        new string[] { "samplecab.cab", "/skip:test",  "/foo", "/replace:A|B" },
      };

    [TestMethod()]
    [DeploymentItem("ONCFInstall.exe")]
    [DeploymentItem("SampleCAB.CAB")]
    public void ParseArgsInvalidTest()
    {
      for (int i = 0; i < m_validArgs.GetLength(0); i++)
      {
        Exception expected = null;
        try
        {
          m_invalidArgs[i][0] = Path.Combine(TestContext.TestDeploymentDir, m_invalidArgs[i][0]);
          CommandLineArgs result = Program_Accessor.ParseArgs(m_invalidArgs[i]);
        }
        catch(Exception ex)
        {
          expected = ex;
        }

        Assert.IsNotNull(expected, string.Format("ParseArgs didn't fail on args[{0}]", i));
      }
    }

    KeyValuePair<string, int>[] m_replaceStrings = new KeyValuePair<string, int>[]
      {
        new KeyValuePair<string, int>("/replace:A|B", 1),
        new KeyValuePair<string, int>("/replace:testA|othertestB", 1),
        new KeyValuePair<string, int>("/replace:testA|othertestB,A|B", 2),
        new KeyValuePair<string, int>("/replace:A|B,", 1),
        new KeyValuePair<string, int>("/replace:testA|othertestB,", 1),
        new KeyValuePair<string, int>("/replace:testA|othertestB,A|B,", 2),
      };

    /// <summary>
    ///A test for ParseReplace
    ///</summary>
    [TestMethod()]
    [DeploymentItem("ONCFInstall.exe")]
    public void ParseReplacePositiveTest()
    {
      foreach (KeyValuePair<string, int> replacestring in m_replaceStrings)
      {
        CommandLineArgs args = new CommandLineArgs();
        Program_Accessor.ParseReplace(replacestring.Key, args);
        Assert.AreEqual(replacestring.Value, args.PathStringReplacements.Count, "Failed to parse " + replacestring.Key);
      }
    }

    [TestMethod()]
    [DeploymentItem("ONCFInstall.exe")]
    public void ParseReplaceNullStringTest()
    {
      ArgumentException expected = null;

      CommandLineArgs args = new CommandLineArgs();

      string replacestring = null;

      try
      {
        Program_Accessor.ParseReplace(replacestring, args);
      }
      catch (ArgumentNullException ex)
      {
        expected = ex;
      }

      Assert.IsNotNull(expected, "null replacestring didn't throw");
    }

    [TestMethod()]
    [DeploymentItem("ONCFInstall.exe")]
    public void ParseReplaceNullArgsTest()
    {
      ArgumentException expected = null;

      CommandLineArgs args = null;

      string replacestring = "/replace:";

      try
      {
        Program_Accessor.ParseReplace(replacestring, args);
      }
      catch (ArgumentNullException ex)
      {
        expected = ex;
      }

      Assert.IsNotNull(expected, "null args didn't throw");
    }

    [TestMethod()]
    [DeploymentItem("ONCFInstall.exe")]
    public void ParseReplaceNoColonTest()
    {
      ArgumentException expected = null;

      CommandLineArgs args = null;

      string replacestring = "file.bin";

      try
      {
        Program_Accessor.ParseReplace(replacestring, args);
      }
      catch (ArgumentException ex)
      {
        expected = ex;
      }

      Assert.IsNotNull(expected, "skip string without colon");
    }

    /// <summary>
    /// ///
    /// </summary>
    [TestMethod()]
    [DeploymentItem("ONCFInstall.exe")]
    public void ParseSkipNullStringTest()
    {
      ArgumentException expected = null;

      CommandLineArgs args = new CommandLineArgs();

      string skipstring = null;

      try
      {
        Program_Accessor.ParseSkip(skipstring, args);
      }
      catch (ArgumentNullException ex)
      {
        expected = ex;
      }

      Assert.IsNotNull(expected, "null skipstring didn't throw");
    }

    [TestMethod()]
    [DeploymentItem("ONCFInstall.exe")]
    public void ParseSkipNullArgsTest()
    {
      ArgumentException expected = null;

      CommandLineArgs args = null;

      string skipstring = "/skip:";

      try
      {
        Program_Accessor.ParseSkip(skipstring, args);
      }
      catch (ArgumentNullException ex)
      {
        expected = ex;
      }

      Assert.IsNotNull(expected, "null args didn't throw");
    }

    [TestMethod()]
    [DeploymentItem("ONCFInstall.exe")]
    public void ParseSkipNoColonTest()
    {
      ArgumentException expected = null;

      CommandLineArgs args = null;

      string skipstring = "file.bin";

      try
      {
        Program_Accessor.ParseSkip(skipstring, args);
      }
      catch (ArgumentException ex)
      {
        expected = ex;
      }

      Assert.IsNotNull(expected, "skip string without colon");
    }

    KeyValuePair<string, int>[] m_skipStrings = new KeyValuePair<string,int>[]
      {
        new KeyValuePair<string, int>("/skip:test1.txt", 1),
        new KeyValuePair<string, int>("/skip:test1.txt,", 1),
        new KeyValuePair<string, int>("/skip:test1.txt,test2.txt", 2),
        new KeyValuePair<string, int>("/skip:test1.txt,test2.txt,", 2),
        new KeyValuePair<string, int>("/skip:folder\\test1.txt,test2.txt", 2),
        new KeyValuePair<string, int>("/skip:\"file name.txt\",test2.txt", 2),
      };

    [TestMethod()]
    [DeploymentItem("ONCFInstall.exe")]
    public void ParseSkipPositiveTest()
    {
      foreach (KeyValuePair<string, int> skipstring in m_skipStrings)
      {
        CommandLineArgs args = new CommandLineArgs();
        Program_Accessor.ParseSkip(skipstring.Key, args);
        Assert.AreEqual(skipstring.Value, args.SkipFiles.Count, "Failed to parse " + skipstring.Key);
      }
    }
  }
}
